#include <pd_gpio.h>
#include <hd_led.h>
#include <hd_key.h>
#include <hd_oled.h>
#include <delay.h>
#include <hd_oled_protocol_i2c.h>
#include <hd_oled_protocol_spi.h>
#include <pd_i2c_hd.h>
#include <pd_i2c_sim.h>
#include <pd_spi_io.h>
#include <stddef.h>
#include <pd_spi_hd.h>
#include <pd_spi_sim.h>
#include <hd_flash.h>
#include "main.h"

#define OLED_I2C            1   // Select a protocol in I2C or SPI
#define OLED_I2C_HARDWARE   1   // Select a protocol in I2C or SPI
#define SPI_HARDWARE        1   // Select hardware or software simulate

static OLED *oled;

extern void SystemClock_Config(void);

extern uint8_t eveSmile[];
extern uint8_t eveSerious[];

int main(void) {
    SystemClock_Config();

    GPIO *spi1SselGPIO[] = {GPIOBuilder.build(GPIOA, LL_GPIO_PIN_2),   // OLED
                            GPIOBuilder.build(GPIOA, LL_GPIO_PIN_4),   // W25Q64 on chip
                            GPIOBuilder.build(GPIOC, LL_GPIO_PIN_4),}; // W25Q64 external
    GPIO *spi1SclkGPIO = GPIOBuilder.build(GPIOA, LL_GPIO_PIN_5); // Clock, SPIx_SCK
    GPIO *spi1MisoGPIO = GPIOBuilder.build(GPIOA, LL_GPIO_PIN_6); // MISO,  SPIx_MISO
    GPIO *spi1MosiGPIO = GPIOBuilder.build(GPIOA, LL_GPIO_PIN_7); // MOSI,  SPIx_MOSI
    SPIGPIO *spi1GPIO = SPIGPIOBuilder.build(spi1SselGPIO, 3, spi1SclkGPIO, spi1MosiGPIO, spi1MisoGPIO);

#ifdef SPI_SIMULATE
    SPISimulate *spiDriver = SPISimulateBuilder.build(spiGPIO)
#elif SPI_HARDWARE
    SPIHardware *spiDriver = SPIHardwareBuilder.build(SPI1, spi1GPIO);
#endif
    SPI *spi1 = (SPI *) spiDriver;
    spi1->init(spi1);

#ifdef OLED_SPI
    GPIO resGPIO = GPIOBuilder.build(GPIOA, LL_GPIO_PIN_3);  // Reset, General IO, the chip reset pin is better
    GPIO dcGPIO = GPIOBuilder.build(GPIOA, LL_GPIO_PIN_1);   // Data or Command, General IO
    OLEDProtocolSPI oledProtocolObj = OLEDProtocolSPIBuilder.build(spi1, &resGPIO, &dcGPIO, &spi1SselGPIO[0]);
#elif OLED_I2C
    GPIO *sckGPIO = GPIOBuilder.build(GPIOB, LL_GPIO_PIN_10);  // I2Cx_SCL
    GPIO *sdaGPIO = GPIOBuilder.build(GPIOB, LL_GPIO_PIN_11);  // I2Cx_SDA
#ifdef OLED_I2C_SIMULATE
    I2CSimulate i2CObj = I2CSimulateBuilder.build(&sckGPIO, &sdaGPIO);
#elif OLED_I2C_HARDWARE
    I2CHardware *i2CObj = I2CHardwareBuilder.build(I2C2, sckGPIO, sdaGPIO);
#endif
    I2C *i2c = (I2C *) i2CObj;
    i2c->init(i2c);
    OLEDProtocolI2C *oledProtocolObj = OLEDProtocolI2CBuilder.build(i2c);
#endif

#if 0
    StorageFlash *sf = StorageFlashBuilder.build();
    OLEDFont *oledFont = OLEDFontBuilder.build((Storage *) sf, ENCODING_UTF8);
    oled = OLEDBuilder.build((OLEDProtocol *) oledProtocolObj, oledFont);
    oled->size = OLED_SIZE_24;
    oled->init(oled);

    oled->printf(oled, 0, 32, "你");
    oled->printf(oled, 80, 32, "好");
    oled->refresh(oled);
    while (1);
#else
    W25Qxx *w25Qxx3OnChip = W25QxxBuilder.build(spi1, spi1SselGPIO[1]);
    w25Qxx3OnChip->init(w25Qxx3OnChip);

    OLEDFont *oledFont = OLEDFontBuilder.build((Storage *) w25Qxx3OnChip, ENCODING_UTF8);
    oled = OLEDBuilder.build((OLEDProtocol *) oledProtocolObj, oledFont);
    oled->size = OLED_SIZE_16;
    oled->init(oled);

    oled->size = OLED_SIZE_12;
    oled->printf(oled, 0, 00, "机EVA");
    oled->printf(oled, 94, 00, "WALE总");
    oled->size = OLED_SIZE_16;
    oled->printf(oled, 0, 16, "器");
    oled->printf(oled, 112, 16, "动");
    oled->size = OLED_SIZE_24;
    oled->printf(oled, 0, 32, "人");
    oled->printf(oled, 104, 32, "员");
    oled->refresh(oled);

    while (1) {
        oled->showImage(oled, 32, 0, 64, 64, eveSmile);
        oled->refresh(oled);
        delay_ms(3000);
        oled->showImage(oled, 32, 0, 64, 64, eveSerious);
        oled->refresh(oled);
        delay_ms(3000);
    }
#endif
}


